#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"

#include "wifi_connect.h"
#include "huawei_iot.h"
#include "nfc_app.h"

#include <cJSON.h>

#include "hi_gpio.h"
#include "hi_io.h"

#include "iot_errno.h"
#include "iot_watchdog.h"
#include "hi_adc.h"
#include "hi_types_base.h"
#include "hi_pwm.h"

#include "cc2530.h"
#include "oled_ssd1306.h"
#include "assistant.h"

#define BEEP_PIN_NAME HI_IO_NAME_GPIO_9
#define BEEP_PIN_FUNCTION 5

#define CONFIG_WIFI_SSID "TP-LINK_201F" //修改为自己的WiFi 热点账号
#define CONFIG_WIFI_PWD "p@ssword"      //修改为自己的WiFi 热点密码

// #define CONFIG_WIFI_SSID "ziniu" //修改为自己的WiFi 热点账号
// #define CONFIG_WIFI_PWD "1qaz2wsx"      //修改为自己的WiFi 热点密码

#define CONFIG_APP_SERVERIP "121.36.42.100" //华为IoT平台IP
#define CONFIG_APP_SERVERPORT "1883"        //华为IoT平台端口

#define CONFIG_APP_DEVICEID "6252d3b42d0897328703e610_Assistant_002" //替换为注册设备后生成的deviceid
#define CONFIG_APP_DEVICEPWD "Assistant_002"                         //替换为注册设备后生成的密钥

#define CONFIG_APP_LIFETIME 60 ///< seconds
#define CONFIG_QUEUE_TIMEOUT (5 * 1000)

#define CONFIG_MOTOR_TIME 400U

#define CONNETING_LED_PIN 9
extern int g_infra;
extern char product[50], wifissid[50], wifipwd[50], deviceid[50], devicepwd[50];
app_cb_t g_app_cb;
osTimerId_t timer_id;
osThreadId_t led_task_id;
osEventFlagsId_t evt_id;

/**
 * @brief 处理数据，并将数据上报到平台
 *
 */
static void deal_report_msg(report_t *report)
{
    oc_mqtt_profile_service_t service;
    oc_mqtt_profile_kv_t infra;       //红外
    oc_mqtt_profile_kv_t temperature; //温度
    oc_mqtt_profile_kv_t humidity;    //湿度
    oc_mqtt_profile_kv_t methane;     //可燃气体
    oc_mqtt_profile_kv_t smoke;       //烟雾
    oc_mqtt_profile_kv_t air_quality; //空气质量

    oc_mqtt_profile_kv_t humidifier;  // 加湿器
    oc_mqtt_profile_kv_t air_cleaner; // 空气净化器

    oc_mqtt_profile_kv_t alarm;

    if (g_app_cb.connected != 1)
    {
        return;
    }

    /* 打包要发送的数据 */
    service.event_time = NULL;
    service.service_id = "Environment";
    service.service_property = &temperature;
    service.nxt = NULL;

    temperature.key = "Temperature";
    temperature.value = &report->Temperature;
    temperature.type = EN_OC_MQTT_PROFILE_VALUE_INT;
    temperature.nxt = &humidity;

    humidity.key = "Humidity";
    humidity.value = &report->Humidity;
    humidity.type = EN_OC_MQTT_PROFILE_VALUE_INT;
    humidity.nxt = &methane;

    methane.key = "Methane";
    methane.value = &report->Methane;
    methane.type = EN_OC_MQTT_PROFILE_VALUE_INT;
    methane.nxt = &smoke;

    smoke.key = "Smoke";
    smoke.value = &report->Smoke;
    smoke.type = EN_OC_MQTT_PROFILE_VALUE_INT;
    smoke.nxt = &air_quality;

    air_quality.key = "AirQuality";
    air_quality.value = &report->AirQuality;
    air_quality.type = EN_OC_MQTT_PROFILE_VALUE_INT;
    air_quality.nxt = &infra;

    infra.key = "Infrared";
    infra.value = &report->Infra;
    infra.type = EN_OC_MQTT_PROFILE_VALUE_INT;
    infra.nxt = &humidifier;

    humidifier.key = "HumidifierStatus";
    humidifier.value = g_app_cb.humidifier_status ? "ON" : "OFF";
    humidifier.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
    humidifier.nxt = &air_cleaner;

    air_cleaner.key = "AirCleanerStatus";
    air_cleaner.value = g_app_cb.air_cleaner_status ? "ON" : "OFF";
    air_cleaner.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
    air_cleaner.nxt = &alarm;

    alarm.key = "AlarmStatus";
    alarm.value = g_app_cb.alarm_status == 1 ? "ON" : "OFF";
    alarm.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
    alarm.nxt = NULL;
    /* 将数据发送到华为IoT平台 */
    oc_mqtt_profile_propertyreport(NULL, &service);
    return;
}

/**
 * @brief 接收从平台下发的数据
 *
 * @param msg 收到的平台消息
 * @return int 处理结果
 */
static int msg_rcv_callback(oc_mqtt_profile_msgrcv_t *msg)
{
    printf("msg_rcv_callback rcv data\n");
    int ret = 0;
    char *buf;
    int buf_len;
    app_msg_t *app_msg;

    if ((NULL == msg) || (msg->request_id == NULL) || (msg->type != EN_OC_MQTT_PROFILE_MSG_TYPE_DOWN_COMMANDS))
    {
        return ret;
    }

    buf_len = sizeof(app_msg_t) + strlen(msg->request_id) + 1 + msg->msg_len + 1;
    buf = malloc(buf_len);
    if (NULL == buf)
    {
        return ret;
    }
    app_msg = (app_msg_t *)buf;
    buf += sizeof(app_msg_t);

    //将接收到的数据打包到结构体
    app_msg->msg_type = en_msg_cmd;
    app_msg->msg.cmd.request_id = buf;
    buf_len = strlen(msg->request_id);
    buf += buf_len + 1;
    memcpy(app_msg->msg.cmd.request_id, msg->request_id, buf_len);
    app_msg->msg.cmd.request_id[buf_len] = '\0';
    buf_len = msg->msg_len;
    app_msg->msg.cmd.payload = buf;
    memcpy(app_msg->msg.cmd.payload, msg->msg, buf_len);
    app_msg->msg.cmd.payload[buf_len] = '\0';

    //将结构体数据放到队列中
    ret = queue_push(g_app_cb.app_msg, app_msg, 10);
    if (ret != 0)
    {
        free(app_msg);
    }

    return ret;
}
/***** 定时器1 回调函数 *****/
void Timer1_Callback(void *arg)
{
    (void)arg;
    osEventFlagsSet(evt_id, 0x00000001U);
    osTimerStop(timer_id);
}

/**
 * @brief 处理平台下发的命令
 *
 * @param cmd 命令内容
 */
static void deal_cmd_msg(cmd_t *cmd)
{
    cJSON *obj_root;
    cJSON *obj_cmdname;
    cJSON *obj_paras;
    cJSON *obj_para;

    int cmdret = 1;
    oc_mqtt_profile_cmdresp_t cmdresp;
    obj_root = cJSON_Parse(cmd->payload);
    if (NULL == obj_root)
    {
        goto EXIT_JSONPARSE;
    }

    obj_cmdname = cJSON_GetObjectItem(obj_root, "command_name");
    if (NULL == obj_cmdname)
    {
        goto EXIT_CMDOBJ;
    }
    if (0 == strcmp(cJSON_GetStringValue(obj_cmdname), "Humidifier_Control"))
    {
        obj_paras = cJSON_GetObjectItem(obj_root, "Paras");
        if (NULL == obj_paras)
        {
            goto EXIT_OBJPARAS;
        }
        obj_para = cJSON_GetObjectItem(obj_paras, "Switch");
        if (NULL == obj_para)
        {
            goto EXIT_OBJPARA;
        }

        if (0 == strcmp(cJSON_GetStringValue(obj_para), "ON"))
        {
            g_app_cb.humidifier_status = 1;
            Assistant_Humidifier_Status(ON);
            printf("Assistant_Humidifier_Status On!\r\n");
        }
        else
        {
            g_app_cb.humidifier_status = 0;
            Assistant_Humidifier_Status(OFF);
            printf("Assistant_Humidifier_Status Off!\r\n");
        }
        cmdret = 0;
    }
    else if (0 == strcmp(cJSON_GetStringValue(obj_cmdname), "AirCleaner_Control"))
    {
        obj_paras = cJSON_GetObjectItem(obj_root, "Paras");
        if (NULL == obj_paras)
        {
            goto EXIT_OBJPARAS;
        }
        obj_para = cJSON_GetObjectItem(obj_paras, "Switch");
        if (NULL == obj_para)
        {
            goto EXIT_OBJPARA;
        }

        if (0 == strcmp(cJSON_GetStringValue(obj_para), "ON"))
        {
            g_app_cb.air_cleaner_status = 1;
            Assistant_AirCtl_Status(ON);
            printf("Assistant_AirCtl_Status On!\r\n");
        }
        else
        {
            g_app_cb.air_cleaner_status = 0;
            Assistant_AirCtl_Status(OFF);
            printf("Assistant_AirCtl_Status Off!\r\n");
        }
        cmdret = 0;
    }
    else if (0 == strcmp(cJSON_GetStringValue(obj_cmdname), "Alarm_Control"))
    {
        obj_paras = cJSON_GetObjectItem(obj_root, "Paras");
        if (NULL == obj_paras)
        {
            goto EXIT_OBJPARAS;
        }
        obj_para = cJSON_GetObjectItem(obj_paras, "Switch");
        if (NULL == obj_para)
        {
            goto EXIT_OBJPARA;
        }

        if (0 == strcmp(cJSON_GetStringValue(obj_para), "ON"))
        {
            g_app_cb.alarm_status = 1;
            Assistant_Alarm_Control(ON);
            printf("Alarm_Control On!\r\n");
        }
        else
        {
            g_app_cb.alarm_status = 0;
            Assistant_Alarm_Control(OFF);
            printf("Alarm_Control Off!\r\n");
        }
        cmdret = 0;
    }

EXIT_OBJPARA:
EXIT_OBJPARAS:
EXIT_CMDOBJ:
    cJSON_Delete(obj_root);
EXIT_JSONPARSE:
    ///< do the response
    cmdresp.paras = NULL;
    cmdresp.request_id = cmd->request_id;
    cmdresp.ret_code = cmdret;
    cmdresp.ret_name = NULL;
    (void)oc_mqtt_profile_cmdresp(NULL, &cmdresp);
    return;
}

/**
 * @brief 传感器采集
 *
 */
static int sensor_task_entry(void)
{
    OledFillScreen(0);
    OledShowString(0, 0, "Sensor| Value", 2);

    char line[32] = {0};

    app_msg_t *app_msg;

    Assistant_Data_TypeDef data;

    Assistant_Init();

    while (1)
    {
        Assistant_Read_Data(&data);

        printf("Temp=%.2f,Humi=%.2f,Gas=%.2f,Infra=%d,Smoke=%.2f,Air=%.2f\n", data.Temperature, data.Humidity, data.Methane, data.Infra, data.Smoke, data.AirQuality);

        snprintf(line, sizeof(line), " Temp : %.2f  ", data.Temperature);
        OledShowString(0, 2, line, 2);

        snprintf(line, sizeof(line), " Humi : %.2f  ", data.Humidity);
        OledShowString(0, 4, line, 2);

        snprintf(line, sizeof(line), "  GAS : %.2f  ", data.Methane);
        OledShowString(0, 6, line, 2);

        sleep(2);

        OledFillScreen(0x00);
        OledShowString(0, 0, "Sensor| Value", 2);

        snprintf(line, sizeof(line), "Infra : %s   ", data.Infra ? "Warning" : "Normal");
        OledShowString(0, 2, line, 2);

        // snprintf(line, sizeof(line), "Smoke : %.2f   ", data.Smoke);
        // OledShowString(0, 4, line, 2);

        // snprintf(line, sizeof(line), "  Air : %.2f   ", data.AirQuality);
        // OledShowString(0, 6, line, 2);

        if (data.Infra && g_app_cb.alarm_status != 0)
        {
            printf("data.Infra = %d\n", data.Infra);
            IoTPwmStart(HI_PWM_PORT_PWM0, 50, 4000);
            sleep(2);
            IoTPwmStop(HI_PWM_PORT_PWM0);
        }
        app_msg = malloc(sizeof(app_msg_t));
        if (NULL != app_msg)
        {
            /* 打包数据并将数据发送到队列中 */
            app_msg->msg_type = en_msg_report;
            app_msg->msg.report.Humidity = data.Humidity;
            app_msg->msg.report.Temperature = data.Temperature;
            app_msg->msg.report.Infra = data.Infra;
            app_msg->msg.report.Methane = data.Methane;
            app_msg->msg.report.Smoke = data.Smoke;
            app_msg->msg.report.AirQuality = data.AirQuality;
            // app_msg->msg.report.AlarmStatus =

            int ret = queue_push(g_app_cb.app_msg, app_msg, CONFIG_QUEUE_TIMEOUT);
            printf("queue_push ret %d\n", ret);
            if (ret != 0)
            {
                free(app_msg);
            }
        }
        sleep(2);
    }

    return 0;
}
/**
 * @brief 云端互通主任务
 *
 */
static int iot_cloud_task_entry(void)
{
    app_msg_t *app_msg;
    uint32_t ret = 1;

    /* 从NFC中读取连接平台相关设备信息 */
    // ret = nfc_get_devived_data();

    OledShowString(0, 2, "Wifi Connetiong", 2);
    /* 连接WiFi热点 */
    if (ret == 0)
    {
        WifiConnect(wifissid, wifipwd);
    }
    else
    {
        WifiConnect(CONFIG_WIFI_SSID, CONFIG_WIFI_PWD);
    }

    OledShowString(0, 4, "IoT Connecting", 2);

    /* 初始化华为云IoT平台 */
    huawei_iot_init();

    /* 打包连接华为云IoT平台所需要的数据 */
    g_app_cb.app_msg = queue_create("queue_rcvmsg", 10, 0);
    if (NULL == g_app_cb.app_msg)
    {
        printf("Create receive msg queue failed\n");
    }
    oc_mqtt_profile_connect_t connect_para;
    (void)memset(&connect_para, 0, sizeof(connect_para));
    connect_para.boostrap = 0;
    if (ret == 0)
    {
        connect_para.device_id = deviceid;      //平台所需要的deviceid
        connect_para.device_passwd = devicepwd; //平台所需要的devicepwd
    }
    else
    {
        connect_para.device_id = CONFIG_APP_DEVICEID;      //平台所需要的deviceid
        connect_para.device_passwd = CONFIG_APP_DEVICEPWD; //平台所需要的devicepwd
    }
    connect_para.server_addr = CONFIG_APP_SERVERIP;   //平台IP
    connect_para.server_port = CONFIG_APP_SERVERPORT; //平台端口

    connect_para.life_time = CONFIG_APP_LIFETIME;
    connect_para.rcvfunc = msg_rcv_callback;
    connect_para.security.type = EN_DTLS_AL_SECURITY_TYPE_NONE;

    /* 连接到华为云IoT平台 */
    printf("Connecting huawei iot cloud!\r\n");
    ret = oc_mqtt_profile_connect(&connect_para);
    if (ret == (int)en_oc_mqtt_err_ok)
    {
        OledShowString(0, 6, "Assistant Ready", 2);
        g_app_cb.connected = 1;
        g_app_cb.alarm_status = -1;
        printf("Huawei iot cloud connect succed!\r\n");

        osThreadTerminate(led_task_id);
        IoTGpioSetOutputVal(CONNETING_LED_PIN, 1);

        //启动采集线程
        osThreadAttr_t attr;
        attr.attr_bits = 0U;
        attr.cb_mem = NULL;
        attr.cb_size = 0U;
        attr.stack_mem = NULL;
        attr.stack_size = 2048 * 10;
        /* 创建传感器数据采集任务 */
        attr.name = "sensor_task_entry";
        attr.priority = 25;
        if (osThreadNew((osThreadFunc_t)sensor_task_entry, NULL, &attr) == NULL)
        {
            printf("Falied to create sensor_task_entry!\n");
        }
    }
    else
    {
        printf("Huawei iot cloud connect faild! Retry\r\n");
        OledShowString(0, 6, "IoT Connect Faild", 2);

        while (1)
        {
            osDelay(100);
        }
    }

    /* 循环读取队列中的数据并根据 msg_type 类型调用对接的处理函数 */
    while (1)
    {
        app_msg = NULL;
        int ret = queue_pop(g_app_cb.app_msg, (void **)&app_msg, 0xFFFFFFFF);
        printf("queue_pop ret %d\n", ret);
        if (NULL != app_msg)
        {
            switch (app_msg->msg_type)
            {
            case en_msg_cmd:
                /* 调用命令处理函数，处理平台下发的命令 */
                deal_cmd_msg(&app_msg->msg.cmd);
                break;

            case en_msg_report:
                /* 调用消息上报处理函数，向平台发送数据 */
                deal_report_msg(&app_msg->msg.report);
                break;

            default:
                break;
            }
            free(app_msg);
        }
        sleep(1);
    }
    return 0;
}

/**
 * @brief 闪灯
 *
 */
static int led_task_entry(void)
{
    // //设置GPIO_2的复用功能为普通GPIO
    // hi_io_set_func(CONNETING_LED_PIN, HI_IO_FUNC_GPIO_9_GPIO);

    // //设置GPIO_2为输出模式
    // hi_gpio_set_dir(CONNETING_LED_PIN, IOT_GPIO_DIR_OUT);

    while (1)
    {
        // IoTGpioSetOutputVal(CONNETING_LED_PIN, 1);
        // sleep(1);
        // IoTGpioSetOutputVal(CONNETING_LED_PIN, 0);
        sleep(1);
    }
    return 0;
}

/**************************************************
 * 任务：motor_task_entry
 * 传感器采集任务
 * ***********************************************/
static int motor_task_entry(void)
{
    oc_mqtt_profile_service_t service;
    oc_mqtt_profile_kv_t motor;
    /* 创建按键事件 */
    evt_id = osEventFlagsNew(NULL);
    if (evt_id == NULL)
    {
        printf("Falied to create EventFlags!\n");
    }

    while (1)
    {
        osEventFlagsWait(evt_id, 0x00000001U, osFlagsWaitAny, osWaitForever);

        g_app_cb.motor = 0;

        /* 打包要发送的数据 */
        service.event_time = NULL;
        service.service_id = "AutoWater";
        service.service_property = &motor;
        service.nxt = NULL;

        motor.key = "MotorStatus";
        motor.value = "OFF";
        motor.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
        motor.nxt = NULL;

        /* 将数据发送到华为IoT平台 */
        oc_mqtt_profile_propertyreport(NULL, &service);
    }
    return 0;
}

// /**
//  * @brief
//  *
//  * @return int
//  */
// static int cc2530_task_entry(void)
// {
//     cc2530_uart_init();
//     uint8_t uart_buff[UART_BUFF_SIZE] = {0};
//     uint8_t *uart_buff_ptr = uart_buff;
//     while(1)
//     {
//         if(cc2530_uart_read(&uart_buff_ptr))
//         {

//         }
//         sleep(5);
//     }
//     return 0;
// }

static void Init(void)
{
    hi_gpio_init();
    // set BEEP pin as PWM function
    hi_io_set_func(BEEP_PIN_NAME, BEEP_PIN_FUNCTION);
    hi_gpio_set_dir(BEEP_PIN_NAME, HI_GPIO_DIR_OUT);
    hi_pwm_init(HI_PWM_PORT_PWM0);
    hi_pwm_set_clock(PWM_CLK_160M);
}

void infra_clear_alarm(char *arg)
{
    g_infra = !g_infra;

    printf("infra_red=%d\n", g_infra);

    // if (g_infra == 0)
    //     IoTPwmStop(HI_PWM_PORT_PWM0);
    // else
    //     IoTPwmStart(HI_PWM_PORT_PWM0, 50, 4000);
}
/**
 * @brief 主程序入口，初始化，启动任务线程
 *
 */
static void main_entry(void)
{
    Init();
    OledInit();
    OledFillScreen(0);
    OledShowString(0, 0, "Family Assitant", 2);

    IoTWatchDogDisable();

    //按键
    hi_io_set_func(HI_IO_NAME_GPIO_5, HI_IO_FUNC_GPIO_5_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_5, HI_GPIO_DIR_IN);
    hi_io_set_pull(HI_IO_NAME_GPIO_5, HI_IO_PULL_UP);
    hi_gpio_register_isr_function(HI_GPIO_IDX_5, HI_INT_TYPE_EDGE, HI_GPIO_EDGE_RISE_LEVEL_HIGH, infra_clear_alarm, NULL);

    printf("=======================================\r\n");
    printf("************Familiy Assistant***********\r\n");
    printf("=======================================\r\n");

    osThreadAttr_t attr;

    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 2048 * 10;
    // /* 创建传感器数据采集任务 */
    // attr.name = "sensor_task_entry";
    // attr.priority = 25;
    // if (osThreadNew((osThreadFunc_t)sensor_task_entry, NULL, &attr) == NULL)
    // {
    //     printf("Falied to create sensor_task_entry!\n");
    // }

    /* 创建端云互通任务 */
    attr.name = "report_task_entry";
    attr.stack_size = 1024 * 20;
    attr.priority = 24;
    if (osThreadNew((osThreadFunc_t)iot_cloud_task_entry, NULL, &attr) == NULL)
    {
        printf("Falied to create report_task_entry!\n");
    }
}

/* 将main_entry任务加入到harmonyOS系统主任务中 */
SYS_RUN(main_entry);